package com.iwgang.familiarrecyclerview;

import ohos.agp.components.BaseItemProvider;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.database.DataSetSubscriber;

import java.util.ArrayList;

/**
 * Wrap FamiliarRecyclerView Adapter
 * Created by iWgang on 15/10/31.
 * https://github.com/iwgang/FamiliarRecyclerView
 */
public class FamiliarWrapRecyclerViewAdapter extends BaseItemProvider {
    private       OnItemClickListener     mOnItemClickListener;
    private       OnItemLongClickListener mOnItemLongClickListener;
    private       BaseItemProvider        mInnerAdapter;
    private       ArrayList<Component>    mHeaderViews       = new ArrayList<>();
    private       ArrayList<Component>    mFooterViews       = new ArrayList<>();
    private       boolean                 isReachedEndOfList = false;
    private       Component               mEmptyView;
    private final int                     HEAD_TYPE          = 11111;
    private final int                     FOOT_TYPE          = 22222;
    private final int                     NORMAL_TYPE        = 0;

    public FamiliarWrapRecyclerViewAdapter(BaseItemProvider innerAdapter) {
        setAdapter(innerAdapter);
    }

    @Override
    public int getCount() {
        if (mInnerAdapter.getCount() > 0) {
            return getHeaderViewsCount() + getFooterViewsCount() + mInnerAdapter.getCount();
        }else {
            if (getEmptyView() != null) {
                return getHeaderViewsCount() + getFooterViewsCount() + 1;
            }
            return getHeaderViewsCount() + getFooterViewsCount();
        }
    }

    @Override
    public Object getItem(int position) {
        if (getItemComponentType(position) == HEAD_TYPE) {
            return getHeaderView();
        } else if (getItemComponentType(position) == FOOT_TYPE) {
            return getFooterView();
        }else {
            return mInnerAdapter.getItemId(position - getHeaderViewsCount());
        }
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public int getItemComponentType(int position) {
        if ((getHeaderViewsCount() > 0) && (position <= getHeaderViewsCount() - 1)) {
            return HEAD_TYPE;
        } else if ((getFooterViewsCount() > 0)
                && (position <= (getCount() - 1)
                        && (position > (getCount() - getFooterViewsCount() - 1)))) {
            return FOOT_TYPE;
        }else {
            return NORMAL_TYPE;
        }
    }

    @Override
    public Component getComponent(int position, Component component, ComponentContainer componentContainer) {
        Component childComponent = null;
        if (getItemComponentType(position) == HEAD_TYPE) {
            childComponent = getHeaderView();
        } else if (getItemComponentType(position) == FOOT_TYPE) {
            childComponent = getFooterView();
        } else {
            if ((mInnerAdapter.getCount() > 0)) {
                childComponent = mInnerAdapter.getComponent(
                        position - getHeaderViewsCount(), component, componentContainer);
            }else {
                childComponent = getEmptyView();
            }
        }
        if (mInnerAdapter.getCount() > 0) {
            childComponent.setClickedListener(new Component.ClickedListener() {
                @Override
                public void onClick(Component component) {
                    if (mOnItemClickListener != null) {
                        mOnItemClickListener.onItemClick(component, position);
                    }
                }
            });
            childComponent.setLongClickedListener(new Component.LongClickedListener() {
                @Override
                public void onLongClicked(Component component) {
                    if (mOnItemLongClickListener != null) {
                        mOnItemLongClickListener.onItemLongClick(component, position);
                    }
                }
            });
        }
        return childComponent;
    }

    public void setAdapter(BaseItemProvider adapter) {
        if (mInnerAdapter != null) {
            this.notifyDataSetItemRangeRemoved(getHeaderViewsCount(), mInnerAdapter.getCount());
            mInnerAdapter.removeDataSubscriber(mDataObserver);
        }
        this.mInnerAdapter = adapter;
        notifyDataChanged();
    }

    public BaseItemProvider getInnerAdapter() {
        return mInnerAdapter;
    }

    public void addHeaderView(Component header) {
        if (header == null) {
            throw new IllegalArgumentException("headerView is null");
        }
        mHeaderViews.add(header);
        notifyDataChanged();
    }

    public void addFooterView(Component footer) {
        if (footer == null) {
            throw new IllegalArgumentException("footerView is null");
        }
        mFooterViews.add(footer);
        notifyDataChanged();
    }

    public Component getFooterView() {
        return mFooterViews.get(0);
    }

    public Component getHeaderView() {
        return mHeaderViews.get(0);
    }

    public void setEmptyView(Component component) {
        if (component != null) {
            this.mEmptyView = component;
            mDataObserver.onChanged();
        }
    }

    public Component getEmptyView() {
        return mEmptyView;
    }

    public void removeHeaderView(Component component) {
        mHeaderViews.remove(component);
        this.notifyDataSetItemRangeChanged(getHeaderViewsCount(), mInnerAdapter.getCount());
    }

    public void removeAllHeaderView() {
        mHeaderViews.clear();
    }

    public void removeFooterView(Component component) {
        mFooterViews.remove(component);
        this.notifyDataSetItemRangeChanged(getHeaderViewsCount(), mInnerAdapter.getCount());
    }

    public void removeAllFooterView() {
        mFooterViews.clear();
        isReachedEndOfList = true;
    }

    public boolean hasReachedEnd() {
        return isReachedEndOfList;
    }

    public int getHeaderViewsCount() {
        return mHeaderViews.size();
    }

    public int getFooterViewsCount() {
        return mFooterViews.size();
    }

    public boolean isHeader(int position) {
        return getHeaderViewsCount() > 0 && position == 0;
    }

    public boolean isFooter(int position) {
        int lastPosition = getCount() - 1;
        return getFooterViewsCount() > 0 && position == lastPosition;
    }

    public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        this.mOnItemClickListener = onItemClickListener;
    }

    public void setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener) {
        this.mOnItemLongClickListener = onItemLongClickListener;
    }

    public interface OnItemClickListener {
        void onItemClick(Component component, int position);
    }

    public interface OnItemLongClickListener {
        void onItemLongClick(Component component, int position);
    }

    private DataSetSubscriber mDataObserver = new DataSetSubscriber() {
        @Override
        public void onChanged() {
            super.onChanged();
            mInnerAdapter.notifyDataChanged();
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount) {
            super.onItemRangeChanged(positionStart, itemCount);
            mInnerAdapter.notifyDataSetItemRangeChanged(positionStart + getHeaderViewsCount(), itemCount);
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            super.onItemRangeInserted(positionStart, itemCount);
            mInnerAdapter.notifyDataSetItemRangeChanged(positionStart + getHeaderViewsCount(), itemCount);
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            super.onItemRangeRemoved(positionStart, itemCount);
            mInnerAdapter.notifyDataSetItemRangeRemoved(positionStart + getHeaderViewsCount(), itemCount);
        }
    };
}
